#if !defined document_h
#define document_h

/** 
 * This file is part of uhferret.
 *
 * Author::    Peter Lane
 * Copyright:: Copyright 2011, Peter Lane.
 * License::   GPLv3
 *
 * uhferret is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * uhferret is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with uhferret.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <cctype>
#include <fstream>
#include <istream>
#include <string>

#include "tokenset.h"
#include "tokenreader.h"

/** Document points to a document on the local filestore.  
  * -- each Document is initialised with a pathname and the type of a document
  *    or it may take these values from a given Document
  * -- the group_id is used to place documents into groups: documents with the same id
  *    will not be compared against each other
  * -- Document owns a TokenReader, which is created on heap during initialisation
  * -- the important part of the class is the set of methods for iterating 
  *    across the trigrams, using ReadTrigram, GetTrigramStart/End and GetToken
  */
class Document
{
	public:
		enum DocumentType { TypeText, TypeCode };
		Document (std::string pathname, DocumentType type = TypeText, int id = 0);
		Document (Document * document);
		// basic information about document: its type and names
		void SetType (DocumentType type);
		bool IsTextType () const;
    std::string GetPathname () const;
		void SetPathname (std::string pathname);
		// accessor/setter for group_id
		int GetGroupId () const;
		void SetGroupId (int id);
		// information about trigrams in document
		int GetTrigramCount () const;
		void SetTrigramCount (int count);
		void ResetTrigramCount ();
		void IncrementTrigramCount ();
		// following methods used to start, read and end processing of trigrams
		bool StartInput (TokenSet & tokenset);
		bool StartInput (std::istream & input, TokenSet & tokenset);
		bool ReadTrigram (TokenSet & tokenset);
		std::size_t GetToken (int i) const;		// access token of current trigram
		std::size_t GetTrigramStart () const;		// access start position of trigram
		std::size_t GetTrigramStart (int i) const;	// access start of token i in trigram
		std::size_t GetTrigramEnd () const;		// access end position of trigram
		void CloseInput ();
		// following methods check the type of the document based on its filename
		bool IsCodeType () const;
		bool IsTxtType () const;
		bool IsUnknownType () const;
	private:
		bool IsFileType (std::string extension) const;
    std::string StringToUpper (std::string) const;
		void InitialiseInput (TokenSet & tokenset);
		std::string	  _pathname; 		// -- source for this document
		DocumentType	  _type;
		int 		  _num_trigrams;
    std::ifstream * _fb;
    std::istream * _cin;
		TokenReader 	* _token_input; // this is a pointer, because initialised separately
		std::size_t	  _current_tuple[3];
		std::size_t	  _current_start[3];
		int		  _group_id;	// an index number indicating this document's group
};

#endif
